package com.chris.security.configurer;

import com.chris.security.filter.MyUsernamePasswordAuthenticationFilter;
import com.chris.security.filter.OptionsRequestFilter;
import com.chris.security.handle.TokenClearLogoutHandler;
import com.chris.security.jwt.JwtAuthorizationFilter;
import com.chris.security.jwt.JwtRefreshSuccessHandler;
import com.chris.security.jwt.JwtUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.web.filter.CorsFilter;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter{

    @Autowired
    private TokenClearLogoutHandler logoutHandle;

    @Autowired
    private JwtUserService jwtUserService;

    @Autowired
    private JwtRefreshSuccessHandler refreshSuccessHandler;

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/image/**").permitAll()
                .antMatchers("/admin/**").hasAnyRole("ADMIN")
                .antMatchers("/article/**").hasRole("USER")
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
                .formLogin().disable()
//                .sessionManagement().disable()
                .cors()
                .and()
//                .headers().addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
//                new Header("Access-control-Allow-Origin","*"),
//                new Header("Access-Control-Expose-Headers","Authorization"))))
//                .and()
                .addFilterAfter(new OptionsRequestFilter(), CorsFilter.class)
//                .apply(new JsonLoginConfigurer<>())
//                .and()
//                .apply(new JwtLoginConfigurer<>()).tokenValidSuccessHandler(refreshSuccessHandler).permissiveRequestUrls("/logout")
                .addFilterAfter(new MyUsernamePasswordAuthenticationFilter(authenticationManager(), jwtUserService), OptionsRequestFilter.class)
                .addFilterAfter(new JwtAuthorizationFilter(authenticationManager(), jwtUserService), MyUsernamePasswordAuthenticationFilter.class)
                .logout()
//		        .logoutUrl("/logout")   //默认就是"/logout"
                .addLogoutHandler(logoutHandle)
                .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
                .and()
                .sessionManagement().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(jwtUserService).passwordEncoder(bCryptPasswordEncoder());
    }


//    @Bean
//    protected CorsConfigurationSource corsConfigurationSource() {
//        CorsConfiguration configuration = new CorsConfiguration();
//        configuration.setAllowedOrigins(Arrays.asList("*"));
//        configuration.setAllowedMethods(Arrays.asList("GET","POST","HEAD", "OPTION"));
//        configuration.setAllowedHeaders(Arrays.asList("*"));
//        configuration.addExposedHeader("Authorization");
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        source.registerCorsConfiguration("/**", configuration);
//        return source;
//    }

}
